package com.coderworm.netty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.nio.charset.StandardCharsets;
import java.util.Set;

public class RtcmAuthHandler extends ChannelInboundHandlerAdapter {
    private final Set<String> allowedIps;
    private final Set<String> authUsers;
    private final String salt;
    // 状态变量：记录验证阶段（0=未验证，1=已验证用户名长度，2=已验证用户名）
    private int authStage = 0;
    private int userNameLen;
    private String userName;

    public RtcmAuthHandler(Set<String> allowedIps, Set<String> authUsers, String salt) {
        this.allowedIps = allowedIps;
        this.authUsers = authUsers;
        this.salt = salt;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 1. 连接建立时校验IP白名单（替代原逻辑的IP校验）
        String clientIp = ctx.channel().remoteAddress().toString().split(":")[0].substring(1);
        if (!allowedIps.contains(clientIp)) {
            ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("ERROR: 未授权IP".getBytes(StandardCharsets.UTF_8)));
            ctx.close(); // IP非法，直接关闭连接
            return;
        }
        System.out.println("客户端连接成功：IP=" + clientIp);
        super.channelActive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        try {
            // 2. 分阶段处理身份验证（异步读取，避免传统IO的阻塞等待）
            while (buf.isReadable()) {
                switch (authStage) {
                    case 0: // 阶段0：读取用户名长度（2字节）
                        if (buf.readableBytes() < 2) return; // 数据不足，等待后续读取（非阻塞，不浪费线程）
                        userNameLen = buf.readShort(); // Netty自动处理大端序，无需手动转换
                        authStage = 1;
                        break;
                    case 1: // 阶段1：读取用户名（userNameLen字节）
                        if (buf.readableBytes() < userNameLen) return; // 数据不足，等待
                        byte[] userNameBytes = new byte[userNameLen];
                        buf.readBytes(userNameBytes);
                        userName = new String(userNameBytes, StandardCharsets.UTF_8);
                        authStage = 2;
                        break;
                    case 2: // 阶段2：读取密码密文（64字节，SHA-256）
                        if (buf.readableBytes() < 64) return; // 数据不足，等待
                        byte[] pwdHashBytes = new byte[64];
                        buf.readBytes(pwdHashBytes);
                        String pwdHash = new String(pwdHashBytes, StandardCharsets.UTF_8);

                        // 3. 校验用户名密码（与原逻辑一致）
                        boolean authSuccess = authUsers.contains(userName + ":" + pwdHash);
                        if (authSuccess) {
                            ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("AUTH_SUCCESS: 验证通过".getBytes(StandardCharsets.UTF_8)));
                            // 验证通过，移除当前Handler（后续数据不再经过身份验证）
                            ctx.pipeline().remove(this);
                        } else {
                            ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("ERROR: 用户名密码错误".getBytes(StandardCharsets.UTF_8)));
                            ctx.close();
                        }
                        authStage = 0;
                        break;
                }
            }
        } finally {
            // 释放ByteBuf资源（Netty关键：避免内存泄漏）
            buf.release();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常处理：打印异常并关闭连接（避免影响其他客户端）
        System.err.println("身份验证异常：" + cause.getMessage());
        ctx.close();
    }
}